package com.bootdo.app.service.impl;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.crypto.symmetric.AES;
import com.alibaba.fastjson.JSON;
import com.bootdo.app.common.aop.exception.BaseException;
import com.bootdo.app.common.aop.exception.ExceptionEnum;
import com.bootdo.app.common.aop.exception.MiniprogramException;
import com.bootdo.app.common.aop.exception.WXException;
import com.bootdo.app.common.config.AuthConfig;
import com.bootdo.app.common.jwt.JWTInfo;
import com.bootdo.app.common.utils.ContextHandlerUtil;
import com.bootdo.app.common.utils.JWTUtil;
import com.bootdo.app.common.utils.StringUtils;
import com.bootdo.app.dto.wx.Code2SessionDto;
import com.bootdo.app.dto.wx.UserDataDto;
import com.bootdo.app.dto.wx.WxUserInfo;
import com.bootdo.app.vo.miniprogram.LoginVo;
import com.bootdo.app.vo.miniprogram.WXUserVo;
import com.bootdo.app.vo.wx.WXUserInfoVo;
import com.bootdo.common.utils.HttpUtil;
import com.bootdo.app.service.MiniProgramService;
import com.bootdo.app.service.WXService;
import com.bootdo.app.vo.wx.Code2SessionVo;
import com.bootdo.system.domain.TbWeixinconfig;
import com.bootdo.system.domain.TbWxuser;
import com.bootdo.system.service.WxConfigService;
import com.bootdo.system.service.WxUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * @auther: 作者: Along
 * @description: 类说明
 * @Date: created in 2020/12/8 23:05
 */
@Slf4j
@Service
public class MiniProgramServiceImpl implements MiniProgramService{

    @Autowired
    private WXService wxService;
    @Autowired
    private AuthConfig authConfig;

    @Autowired
    private WxUserService wxUserService;
    @Autowired
    private WxConfigService wxConfigService;



    /**
     * 微信小程序用户授权登陆 换取 jwt-token
     * @param code2SessionDto
     * @return
     */
    @Override
    public LoginVo login(Code2SessionDto code2SessionDto) {
        log.info("微信小程序 login : code2SessionDto = {}",code2SessionDto);
        TbWeixinconfig wxConfig = wxConfigService.selectByAppId(code2SessionDto.getAppId());
        if(wxConfig == null){
            throw new MiniprogramException(ExceptionEnum.WX_INVALID_APPID);
        }
        log.info("微信配置：appId = {},appSecret = {},sid = {}",wxConfig.getAppid(),wxConfig.getAppsecret(),wxConfig.getAdminId());
        String sid = wxConfig.getAdminId().toString();
        Code2SessionVo code2SessionVo = wxService.code2Session(code2SessionDto.getAppId(),wxConfig.getAppsecret(),code2SessionDto.getCode());
        Integer errCode = code2SessionVo.getErrcode();
        if(errCode != null && errCode != 0){
            throw new WXException(code2SessionVo.getErrcode(),code2SessionVo.getErrmsg());
        }
        log.info("微信小程序接口返回信息 : code2SessionVo = {}",code2SessionVo);
        String openid = code2SessionVo.getOpenid();
        String sessionKey = code2SessionVo.getSession_key();
        String unionid = code2SessionVo.getUnionid();
        TbWxuser wxUser;
        if(StringUtils.isNotEmpty(unionid)){ // 说明用户 关注过公众号
            wxUser = wxUserService.getUserByUnioId(unionid);
            log.info("根据 unionId 查询微信用户信息:{}",wxUser);
        }else{
            wxUser = wxUserService.selectByWxOpenId(openid);
            log.info("根据 openId 查询微信用户信息:{}",wxUser);
        }
        WXUserVo userVo = null;
        if(wxUser == null){
            // 说明用户不存在，需要去解密用户数据，解密用户数据，需要session_key
            wxUser = new TbWxuser();
            wxUser.setSid(sid);
            if(StringUtils.isNotEmpty(code2SessionDto.getWxuser_id())){
                // 上级代理
                wxUser.setWxuserId(Integer.valueOf(code2SessionDto.getWxuser_id()));
                //wxUserService.select
            }
            if(StringUtils.isNotEmpty(code2SessionDto.getWxuser_sub_id())){
                // 二级代理
                wxUser.setWxuserSubId(Integer.valueOf(code2SessionDto.getWxuser_sub_id()));
            }
            wxUser.setOpenidXcx(openid);
            wxUserService.insert2update(wxUser);
            //修改当前微信等级
            wxUserService.selectLeaderNum(wxUser.getWxuserId(),wxConfig.getAppid());
        }else {
            userVo = new WXUserVo();
            BeanUtils.copyProperties(wxUser,userVo);
        }
        String token;
        try {
            // 生成JWT中，包含用户的 id，sid,openId,sessionKey
            token = JWTUtil.generateToken(new JWTInfo(openid, wxUser.getId().toString(), sessionKey, sid), authConfig.getPriKeyByte(), authConfig.getJwtExpire());
        } catch (Exception e) {
            log.error("JWT生成异常:{}",e);
            throw new BaseException(e);
        }
        return LoginVo.builder().id(wxUser.getId()).token(token).wxUserVo(userVo).build();
    }

    /**
     * 解密微信小程序用户信息
     * @param userDataDto
     * @return
     */
    @Override
    public WXUserVo decodeUserData(UserDataDto userDataDto) {
        String sessionKey = ContextHandlerUtil.getSessionKey();

        Integer bizId = userDataDto.getBizId();
        TbWxuser tbWxuser = wxUserService.getById(bizId);
        if(tbWxuser == null){
            throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_LOGIN_ERROR);
        }
        String iv = userDataDto.getIv();
        String encryptedData = userDataDto.getEncryptedData();
        System.out.println(encryptedData);
        WXUserVo wxUserVo = new WXUserVo();
        try {
            AES aes = new AES("CBC","PKCS7Padding", Base64Decoder.decode(sessionKey),Base64Decoder.decode(iv));
            String result = aes.decryptStr(Base64Decoder.decode(encryptedData));
            System.out.println(result);
            WXUserInfoVo wxUserInfoVo = JSON.parseObject(result, WXUserInfoVo.class);
            log.info("解密微信小程序用户信息:{}", wxUserInfoVo);
            tbWxuser.setNickname(wxUserInfoVo.getNickName());
            tbWxuser.setHeadimgurl(wxUserInfoVo.getAvatarUrl());
            tbWxuser.setSex(wxUserInfoVo.getGender());
            tbWxuser.setCity(wxUserInfoVo.getCity());
            tbWxuser.setProvince(wxUserInfoVo.getProvince());
            tbWxuser.setCountry(wxUserInfoVo.getCountry());
            tbWxuser.setWxUnionId(wxUserInfoVo.getUnionId());
            tbWxuser.setOpenidXcx(wxUserInfoVo.getOpenId());
        } catch (Exception e) {
            log.error("微信小程序用户信息解析异常:{}",e);
            WxUserInfo userInfo = userDataDto.getUserInfo();
            tbWxuser.setNickname(userInfo.getNickName());
            tbWxuser.setHeadimgurl(userInfo.getAvatarUrl());
            tbWxuser.setSex(userInfo.getGender().toString());
            tbWxuser.setCity(userInfo.getCity());
            tbWxuser.setProvince(userInfo.getProvince());
            tbWxuser.setCountry(userInfo.getCountry());
        }
        wxUserService.insert2update(tbWxuser);
        BeanUtils.copyProperties(tbWxuser,wxUserVo);
        return wxUserVo;
    }

	@Override
	public String decodeUserData2(UserDataDto userDataDto) {
		String sessionKey = ContextHandlerUtil.getSessionKey();

        Integer bizId = userDataDto.getBizId();
        TbWxuser tbWxuser = wxUserService.getById(bizId);
        if(tbWxuser == null){
            throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_LOGIN_ERROR);
        }
        String iv = userDataDto.getIv();
        String encryptedData = userDataDto.getEncryptedData();
        System.out.println(encryptedData);
        try {
            AES aes = new AES("CBC","PKCS7Padding", Base64Decoder.decode(sessionKey),Base64Decoder.decode(iv));
            String result = aes.decryptStr(Base64Decoder.decode(encryptedData));
            System.out.println(result);
            WXUserInfoVo wxUserInfoVo = JSON.parseObject(result, WXUserInfoVo.class);
            log.info("解密微信小程序用户信息:{}", wxUserInfoVo);
            tbWxuser.setMobile(wxUserInfoVo.getPhoneNumber());
        } catch (Exception e) {
            log.error("微信小程序用户信息解析异常:{}",e);
        }
        wxUserService.insert2update(tbWxuser);
        return tbWxuser.getMobile();
	}
}
